import kotlin.properties.Delegates
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

// kotlin 自带代理实现，不需要写代码，编译时自动生成
interface Base {
    fun hi()
    fun oh()
}

class BaseOne: Base {
    override fun hi() = println("hello")
    override fun oh() = println("oh")
}

// 代理衍生类, 编译时会自动生成代理实现
class Derived(b: Base): Base by b {

    override fun oh() = println("shit")

}

fun main01() {
    val d = Derived(BaseOne())
    d.hi()  // 代理最终调用BaseOne
    d.oh()  // 调用代理类的override方法
}


// 属性代理
class MyDelegate {
    // 代理获取值的时候
    operator fun getValue(p: P, property: KProperty<*>): String {
        return "$p, delegating variable name is : '${property.name}'"
    }

    operator fun setValue(p: P, property: KProperty<*>, value: String) {
        println("'$value' has been assigned to '${property.name}' in '$p'")
    }
}

class P {
    var p: String by MyDelegate()
}

fun main02() {
    val pp = P()
    pp.p = "hello"
    println(pp.p)
}


// lazy 代理 延时初始化, lazy只能代理val变量
// lazy初始化过程默认线程安全，如果确定没有多线程占用，可以by lazy(LazyThreadSafetyMode.NONE)
val lazyValue: String by lazy {
    println("print on first used")
    "lazyO"
}

fun main03() {
    println(lazyValue)
    println(lazyValue)  // 不再打印lazy初始化的print
}

// 代理观察者，监控值变化并调用handler
class User {
    var name: String by Delegates.observable("dog") { // 当值发生变化时将会调用该handler
            prop, old, new -> println("${prop.name} oldValue: $old, newValue: $new")
    }
}

fun main04() {
    val u = User()
    u.name = "One"
    u.name = "Two"
}

// 代理其他属性  ::
var value1: Int = 0
class Class2(var value2: Int)
class MyValues(var value3: Int, private val clazz2: Class2) {
    var delegatedValue3: Int by this::value3 // 代理本类的value3
    var delegatedValue2: Int by clazz2::value2  // 代理class2的value2
    var delegatedValue1: Int by ::value1 // 代理value1
}

// 代理其他属性，一般用于兼容性操作，当旧的字段废除新字段产生时，使用代理
class MyClass3 {
    var newName: Int = 0
    @Deprecated("use newName instead", ReplaceWith("newName"))
    var oldName: Int by this::newName
}

fun main() {
    val myClass3 = MyClass3()
    myClass3.oldName = 1
    print(myClass3.newName)
}


// 代理map中的key为属性
class Apple(private val map: Map<String, Any?>) {  // 此处map只读
    val name: String by map  // 所以属性需为val
    val price: Int by map
}
class Egg(private val map: MutableMap<String, Any?>) {
    var name: String by map  // MutableMap可变，所以属性可以为var
    var price: Int by map
}

fun delegateMapDemo() {
    val apple = Apple(mapOf("name" to "bigApple", "price" to 10))
    println("apple name: ${apple.name}, price: ${apple.price}")
}


// 对于属性代理，除了编写如：MyDelegate代理类外，kotlin提供了接口定义
// 实现接口或者匿名实现一样可以作为代理类
// ReadWriteProperty、 ReadOnlyProperty分别代表读写代理和只读代理接口
// 匿名代理函数，返回代理对象
fun demoDelegate(): ReadWriteProperty<Any?, Int> =
    object : ReadWriteProperty<Any?, Int> {
        var currentValue = 0
        override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
            currentValue = value
        }

        override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
            return currentValue
        }

    }
// 代理变量
val readWriteValue: Int by demoDelegate()


// kotlin还提供了 provideDelegate，多数应用场景用来做值检查，类似于aop
class PenDelegate<T>(private val value: T): ReadOnlyProperty<MyPen, T> {
    override fun getValue(thisRef: MyPen, property: KProperty<*>): T {
        return value
    }
}

class ValueLoader<T>(private val value: T) {
    operator fun provideDelegate(thisRef: MyPen, prop: KProperty<*>)
    : ReadOnlyProperty<MyPen, T> {
        // check value logic
        println("check logic for value: $value")
        return PenDelegate(value)
    }
}

class MyPen {
    private fun <T> bindLoader(value: T): ValueLoader<T> {
        return ValueLoader(value)
    }

    val size by bindLoader(10)
    val line by bindLoader(20)
}

fun main1(args: Array<String>) {
    println("${MyPen().size}")
}




